package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.constant.MqConstant;
import cn.com.dcsgo.domain.OrderItem;
import cn.com.dcsgo.dto.*;
import cn.com.dcsgo.enums.OrderStatus;
import cn.com.dcsgo.exception.BusinessException;
import cn.com.dcsgo.feign.CartFeignClient;
import cn.com.dcsgo.feign.MemberFeignClient;
import cn.com.dcsgo.feign.ProdFeignClient;
import cn.com.dcsgo.feign.ShopFeignClient;
import cn.com.dcsgo.mapper.OrderItemMapper;
import cn.com.dcsgo.model.ProdConfirmModel;
import cn.com.dcsgo.model.ShopOrder;
import cn.com.dcsgo.settlement.OrderAmountCalculatorFactory;
import cn.com.dcsgo.settlement.OrderAmountContext;
import cn.com.dcsgo.settlement.model.Commodity;
import cn.com.dcsgo.utils.AuthUtil;
import cn.com.dcsgo.vo.*;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.com.dcsgo.domain.Order;
import cn.com.dcsgo.service.OrderService;
import cn.com.dcsgo.mapper.OrderMapper;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 针对表【order(订单表)】的数据库操作Service实现
 *
 * @author Dcsgo
 * @since 2025-11-16 13:32:37
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
        implements OrderService {

    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private MemberFeignClient memberFeignClient;

    @Resource
    private ShopFeignClient shopFeignClient;

    @Resource
    private ProdFeignClient prodFeignClient;

    @Resource
    private CartFeignClient cartFeignClient;

    @Resource
    private OrderAmountCalculatorFactory orderAmountCalculatorFactory;

    @Resource
    private Snowflake snowflake;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public OrderAmountVO getOrderAmountVO(String openid) {
        List<Order> orderList = list(
                new LambdaQueryWrapper<Order>()
                        .select(Order::getStatus)
                        .eq(Order::getOpenId, openid)
        );
        OrderAmountVO orderAmountVO = new OrderAmountVO(0L, 0L, 0L);
        if (orderList.isEmpty()) {
            return orderAmountVO;
        }
        long unPay = 0;
        long payed = 0;
        long consignment = 0;
        for (Order order : orderList) {
            // 订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败
            if (OrderStatus.PENDING_PAYMENT.getCode() == order.getStatus()) {
                unPay++;
            } else if (OrderStatus.PENDING_SHIPMENT.getCode() == order.getStatus()) {
                payed++;
            } else if (OrderStatus.PENDING_RECEIPT.getCode() == order.getStatus()) {
                consignment++;
            }
        }
        orderAmountVO.setUnPay(unPay);
        orderAmountVO.setPayed(payed);
        orderAmountVO.setConsignment(consignment);
        return orderAmountVO;
    }

    @Override
    public Page<OrderVO> getOrderVOPage(String openid, Integer status, PageDTO pageDTO) {
        Page<OrderVO> orderVOPage = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());
        Page<Order> orderPage = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());
        baseMapper.selectPage(orderPage,
                new LambdaQueryWrapper<Order>()
                        .eq(Order::getOpenId, openid)
                        // 0全部、1待支付、2待发货、3待收货、5已完成（除0外其它与数据库一致）
                        .eq(status != 0, Order::getStatus, status)
                        .orderByDesc(Order::getCreateTime)
        );
        if (CollectionUtils.isEmpty(orderPage.getRecords())) {
            return orderVOPage;
        }

        orderVOPage.setTotal(orderPage.getTotal());
        orderVOPage.setPages(orderPage.getPages());

        // 将Order转换成OrderVO
        orderVOPage.setRecords(
                orderPage.getRecords().stream().map(order -> {
                    OrderVO orderVO = new OrderVO();
                    BeanUtil.copyProperties(order, orderVO);
                    return orderVO;
                }).toList()
        );

        // 查询OrderItem
        Set<String> orderNumberSet = orderPage.getRecords().stream().map(Order::getOrderNumber).collect(Collectors.toSet());
        List<OrderItem> orderItemList = orderItemMapper.selectList(
                new LambdaQueryWrapper<OrderItem>()
                        .in(OrderItem::getOrderNumber, orderNumberSet)
        );

        // 设置OrderVO里面的OrderItemVO
        Map<String, List<OrderItem>> orderItemMap = orderItemList.stream().collect(Collectors.groupingBy(OrderItem::getOrderNumber));
        orderVOPage.getRecords().forEach(orderVO -> {
            List<OrderItem> orderItems = orderItemMap.get(orderVO.getOrderNumber());
            if (!CollectionUtils.isEmpty(orderItems)) {
                orderVO.setOrderItemList(
                        orderItems.stream().map(orderItem -> {
                            OrderItemVO orderItemVO = new OrderItemVO();
                            BeanUtil.copyProperties(orderItem, orderItemVO);
                            return orderItemVO;
                        }).toList()
                );
            }
        });

        return orderVOPage;
    }

    @Override
    public Page<Order> getOrderPage(PageDTO pageDTO, OrderQueryDTO orderQueryDTO) {
        // TODO 订单表设计不合理，没有包含店铺ID，店铺ID却被放到了订单项里面？！
        //  在下单时应该按店铺进行拆单。如果非要将多个店铺的商品合在一个订单里，那也应该通过
        //  店铺ID将其拆分为多个子订单，但这样有点没必要，因为用户也不纠结这些。
        if (AuthUtil.getShopId() != 1) {
            throw new BusinessException("目前尚不支持非超级店铺查看订单数据");
        }
        Page<Order> orderPage = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());
        Integer status = orderQueryDTO.getStatus();
        String orderNumber = orderQueryDTO.getOrderNumber();
        LocalDateTime startTime = orderQueryDTO.getStartTime();
        LocalDateTime endTime = orderQueryDTO.getEndTime();
        page(orderPage,
                new LambdaQueryWrapper<Order>()
                        .eq(StringUtils.hasText(orderNumber), Order::getOrderNumber, orderNumber)
                        .eq(status != null, Order::getStatus, status)
                        .ge(startTime != null, Order::getCreateTime, startTime)
                        .le(endTime != null, Order::getCreateTime, endTime)
        );
        // 查询关联的订单项
        Set<String> orderNumberSet = orderPage.getRecords().stream().map(Order::getOrderNumber).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(orderNumberSet)) {
            return orderPage;
        }
        List<OrderItem> orderItemList = orderItemMapper.selectList(
                new LambdaQueryWrapper<OrderItem>()
                        .in(OrderItem::getOrderNumber, orderNumberSet)
        );
        // 设置Order中的OrderItems
        Map<String, List<OrderItem>> orderItemMap = orderItemList.stream().collect(Collectors.groupingBy(OrderItem::getOrderNumber));
        orderPage.getRecords().forEach(order -> {
            List<OrderItem> orderItems = orderItemMap.get(order.getOrderNumber());
            if (!CollectionUtils.isEmpty(orderItems)) {
                order.setOrderItems(orderItems);
            }
        });
        return orderPage;
    }

    @Override
    public Order getByOrderNumber(String orderNumber) {
        Order order = baseMapper.selectOne(
                new LambdaQueryWrapper<Order>()
                        .eq(Order::getOrderNumber, orderNumber)
        );
        order.setOrderItems(
                orderItemMapper.selectList(
                        new LambdaQueryWrapper<OrderItem>()
                                .eq(OrderItem::getOrderNumber, order.getOrderNumber())
                )
        );
        return order;
    }

    @Override
    public OrderConfirmVO confirmOrder(OrderConfirmDTO orderConfirmDTO) {
        OrderConfirmVO orderConfirmVO = new OrderConfirmVO();
        //0.获取会员默认收货地址
        String openid = AuthUtil.getOpenid();
        MemberAddressDTO memberDefaultAddress = memberFeignClient.getMemberDefaultAddress(openid);
        orderConfirmVO.setMemberAddr(memberDefaultAddress);
        //1.根据确认订单请求参数判断是来自购物车的订单确认还是直接来自商品的订单确认
        OrderAmountContext orderAmountContext = new OrderAmountContext();
        if (!CollectionUtils.isEmpty(orderConfirmDTO.getBasketIds())) {
            handleConfirmFromCart(orderConfirmDTO, orderConfirmVO, orderAmountContext);
        } else if (orderConfirmDTO.getOrderItem() != null) {
            handleConfirmFromProd(orderConfirmDTO, orderConfirmVO, orderAmountContext);
        } else {
            throw new BusinessException("订单确认必须包含购物车信息或商品信息");
        }
        //2.计算总计信息
        //totalCount,totalMoney,actualTotal,transfee,shopReduce
        orderAmountCalculatorFactory.getOrderAmountCalculator().calculate(orderAmountContext);
        Integer totalCount = orderAmountContext.getCommodities().stream().map(Commodity::getCount).reduce(Integer::sum).orElse(0);
        BigDecimal totalMoney = orderAmountContext.getCommoditiesAmount();
        BigDecimal shopReduce = orderAmountContext.getDiscountAmount();
        BigDecimal transfee = orderAmountContext.getFreight();
        BigDecimal actualTotal = orderAmountContext.getActualPaymentAmount();
        orderConfirmVO.setTotalCount(totalCount);
        orderConfirmVO.setTotalMoney(totalMoney);
        orderConfirmVO.setActualTotal(actualTotal);
        orderConfirmVO.setTransfee(transfee);
        orderConfirmVO.setShopReduce(shopReduce);
        return orderConfirmVO;
    }

    @Override
    @GlobalTransactional
    public OrderSubmitVO submitOrder(OrderSubmitDTO orderSubmitDTO) {
        //0.生成订单编号（雪花算法）
        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        String orderNumber = createOrderNumber();
        log.debug("orderNumber:{}", orderNumber);
        //1.如果订单来自购物车则删除购物车中相关购物项
        //订单来源（0购物车，1直接购买商品）
        if (orderSubmitDTO.getOrderEntry() == 0) {
            removeCartItem(orderSubmitDTO);
        }
        //2.更新库存
        StockUpdateDTO stockUpdateDTO = updateProdStock(orderSubmitDTO);
        //3.添加订单数据
        saveOrder(orderNumber, orderSubmitDTO);
        //4.订单回滚的延时消息（用户超时未支付回滚库存和修改订单状态）
        sendDelayedMessage(orderNumber, stockUpdateDTO);
        return orderSubmitVO;
    }

    @Override//TODO 回滚订单失败了咋办？
    public boolean rollBackOrder(Order order, StockUpdateDTO stockUpdateDTO) {
        // 更新订单信息
        order.setCloseType(1);// 1表示超时未支付
        order.setStatus(OrderStatus.FAILED.getCode());
        boolean ok = updateById(order);
        if (!ok) {
            throw new BusinessException("回滚订单时更新订单信息失败");
        }
        // 回滚商品库存
        stockUpdateDTO.getProdStockUpdateDTOList().forEach(prod -> prod.setCount(-prod.getCount()));
        stockUpdateDTO.getProdSkuStockUpdateDTOList().forEach(sku -> sku.setCount(-sku.getCount()));
        ok = prodFeignClient.updateStock(stockUpdateDTO);
        if (!ok) {
            throw new BusinessException("回滚订单关联的商品库存失败");
        }
        return true;
    }

    private void sendDelayedMessage(String orderNumber, StockUpdateDTO stockUpdateDTO) {
        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(stockUpdateDTO))
                .setHeader(RocketMQHeaders.KEYS, orderNumber).build();
        //messageDelayLevel	1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
        // 超时时间6000ms，消息延时为30m
        SendResult sendResult = rocketMQTemplate.syncSend(MqConstant.ORDER_MS_TOPIC, message, 6000, 16);
        log.info("发送订单延时消息，订单号为：{}，发送结果为：{}", orderNumber, sendResult.getSendStatus());
    }

    private void saveOrder(String orderNumber, OrderSubmitDTO orderSubmitDTO) {
        // 重新计算结算金额（前端传递的金额数据忽略不用）
        OrderAmountContext orderAmountContext = new OrderAmountContext();
        List<OrderItem> orderItemList = orderSubmitDTO.getShopOrders().stream().flatMap(shopOrder -> shopOrder.getShopOrderItems().stream()).toList();
        List<Commodity> commodities = new ArrayList<>(orderItemList.size());
        Set<Long> skuIds = orderItemList.stream().map(OrderItem::getSkuId).collect(Collectors.toSet());
        List<SkuDTO> skuList = prodFeignClient.getSkuDTOListBySkuIds(skuIds);
        Map<Long, OrderItem> skuOrderItemMap = orderItemList.stream().collect(Collectors.toMap(OrderItem::getSkuId, orderItem -> orderItem));
        // 添加订单项
        skuList.forEach(sku -> {
            Commodity commodity = new Commodity();
            commodity.setSkuId(sku.getSkuId());
            commodity.setCount(skuOrderItemMap.get(sku.getSkuId()).getProdCount());
            commodity.setPrice(sku.getPrice());
            commodities.add(commodity);

            OrderItem orderItemSaveData = new OrderItem();
            BeanUtil.copyProperties(skuOrderItemMap.get(sku.getSkuId()), orderItemSaveData);
            orderItemSaveData.setPrice(commodity.getPrice());
            orderItemSaveData.setProductTotalAmount(commodity.getPrice().multiply(BigDecimal.valueOf(commodity.getCount())));
            orderItemSaveData.setOrderNumber(orderNumber);
            orderItemSaveData.setCommSts(0);//默认未评论
            orderItemMapper.insert(orderItemSaveData);
        });
        orderAmountContext.setCommodities(commodities);
        orderAmountCalculatorFactory.getOrderAmountCalculator().calculate(orderAmountContext);
        // 添加订单
        String openid = AuthUtil.getOpenid();
        Order order = new Order();
        order.setOpenId(openid);
        order.setOrderNumber(orderNumber);
        order.setTotalMoney(orderAmountContext.getCommoditiesAmount());
        order.setActualTotal(orderAmountContext.getActualPaymentAmount());
        order.setFreightAmount(orderAmountContext.getFreight());
        order.setRemarks(orderSubmitDTO.getRemarks());
        order.setStatus(OrderStatus.PENDING_PAYMENT.getCode());//刚提交订单状态是代付款
        StringBuilder addrOrderDetails = new StringBuilder();
        MemberAddressDTO memberAddr = orderSubmitDTO.getMemberAddr();
        addrOrderDetails.append(memberAddr.getProvince())
                .append(memberAddr.getCity())
                .append(memberAddr.getArea())
                .append(memberAddr.getAddr())
                .append(" 收件人：").append(memberAddr.getReceiver())
                .append(" 手机号：").append(memberAddr.getMobile());
        order.setAddrOrderDetails(addrOrderDetails.toString());
        order.setProductNums(orderAmountContext.getCommodities().stream()
                .map(Commodity::getCount).reduce(Integer::sum)
                .orElseThrow(() -> new BusinessException("请求参数有误")));
        order.setIsPayed(0);//刚提交订单还未支付
        order.setDeleteStatus(0);
        order.setRefundSts(0);
        order.setReduceAmount(orderAmountContext.getDiscountAmount());
        baseMapper.insert(order);
    }

    private StockUpdateDTO updateProdStock(OrderSubmitDTO orderSubmitDTO) {
        StockUpdateDTO stockUpdateDTO = new StockUpdateDTO();
        List<OrderItem> orderItemList = orderSubmitDTO.getShopOrders().stream()
                .flatMap(shopOrder -> shopOrder.getShopOrderItems().stream()).toList();
        Map<Long, List<OrderItem>> prodItemMap = orderItemList.stream().collect(Collectors.groupingBy(OrderItem::getProdId));
        List<ProdStockUpdateDTO> prodStockUpdateDTOList = new ArrayList<>(prodItemMap.keySet().size());
        List<ProdSkuStockUpdateDTO> prodSkuStockUpdateDTOList = new ArrayList<>(orderItemList.size());
        for (Long prodId : prodItemMap.keySet()) {
            ProdStockUpdateDTO prod = new ProdStockUpdateDTO();
            prod.setProdId(prodId);
            prod.setCount(prodItemMap.get(prodId).stream().map(OrderItem::getProdCount).reduce(Integer::sum).orElse(0));
            prodStockUpdateDTOList.add(prod);
            prodSkuStockUpdateDTOList.addAll(
                    prodItemMap.get(prodId).stream().map(orderItem -> {
                        ProdSkuStockUpdateDTO sku = new ProdSkuStockUpdateDTO();
                        sku.setCount(orderItem.getProdCount());
                        sku.setSkuId(orderItem.getSkuId());
                        return sku;
                    }).toList()
            );
        }
        stockUpdateDTO.setProdStockUpdateDTOList(prodStockUpdateDTOList);
        stockUpdateDTO.setProdSkuStockUpdateDTOList(prodSkuStockUpdateDTOList);
        boolean ok = prodFeignClient.updateStock(stockUpdateDTO);
        if (!ok) {
            log.error("更新库存失败！");
            throw new BusinessException("下单失败");
        }
        return stockUpdateDTO;
    }

    /**
     * 移除订单中关联的购物车数据
     */
    private void removeCartItem(OrderSubmitDTO orderSubmitDTO) {
        String openid = AuthUtil.getOpenid();
        List<Long> skuIds = orderSubmitDTO.getShopOrders().stream()
                .flatMap(shopOrder -> shopOrder.getShopOrderItems().stream())
                .map(OrderItem::getSkuId).toList();
        boolean ok = cartFeignClient.removeCartItem(openid, skuIds);
        if (!ok) {
            log.error("提交订单，移除购物车相关数据失败！");
        }
    }

    private String createOrderNumber() {
        return snowflake.nextIdStr();
    }

    /**
     * 处理来自购物车的订单确认
     */
    private void handleConfirmFromCart(OrderConfirmDTO orderConfirmDTO, OrderConfirmVO orderConfirmVO, OrderAmountContext orderAmountContext) {
        //OrderConfirmVO:{收货地址（已处理）,ShopOrder:{shopId,shopName,List<OrderItem>:[{}]},totalCount,totalMoney,actualTotal,transfee,shopReduce}
        //获取购物车信息
        List<Long> basketIds = orderConfirmDTO.getBasketIds();
        List<CartInfoDTO> basketList = cartFeignClient.getBasketList(basketIds);
        //获取店铺信息
        Set<Long> shopIds = basketList.stream().map(CartInfoDTO::getShopId).collect(Collectors.toSet());
        List<ShopInfoDTO> shopInfoDTOList = shopFeignClient.getShopInfoDTOList(shopIds);
        Map<Long, ShopInfoDTO> shopInfoDTOMap = shopInfoDTOList.stream().collect(Collectors.toMap(ShopInfoDTO::getShopId, shopInfo -> shopInfo));
        List<ShopOrder> shopOrderList = new ArrayList<>(shopInfoDTOList.size());
        //设置店铺信息
        shopIds.forEach(shopId -> {
            ShopOrder shopOrder = new ShopOrder();
            shopOrder.setShopId(shopId);
            shopOrder.setShopName(shopInfoDTOMap.get(shopId).getShopName());
            shopOrderList.add(shopOrder);
        });
        //获取SKU信息
        List<SkuDTO> skuList = prodFeignClient.getSkuDTOListBySkuIds(Set.copyOf(basketList.stream().map(CartInfoDTO::getSkuId).toList()));
        Map<Long, SkuDTO> skuMap = skuList.stream().collect(Collectors.toMap(SkuDTO::getSkuId, sku -> sku));
        Map<Long, List<CartInfoDTO>> shopCartMap = basketList.stream().collect(Collectors.groupingBy(CartInfoDTO::getShopId));
        //设置OrderItem
        orderAmountContext.setCommodities(new ArrayList<>(skuList.size()));
        shopOrderList.forEach(shopOrder -> {
            Long shopId = shopOrder.getShopId();
            List<CartInfoDTO> cartInfos = shopCartMap.get(shopId);
            List<OrderItem> orderItemList = new ArrayList<>(cartInfos.size());
            cartInfos.forEach(cartInfo -> {
                OrderItem item = new OrderItem();
                BeanUtil.copyProperties(cartInfo, item);
                BeanUtil.copyProperties(skuMap.get(cartInfo.getSkuId()), item);
                item.setProductTotalAmount(item.getPrice().multiply(BigDecimal.valueOf(item.getProdCount())));
                orderItemList.add(item);
                Commodity commodity = new Commodity();
                commodity.setSkuId(item.getSkuId());
                commodity.setPrice(item.getPrice());
                commodity.setCount(item.getProdCount());
                orderAmountContext.getCommodities().add(commodity);
            });
            shopOrder.setShopOrderItems(orderItemList);
        });
        orderConfirmVO.setShopOrders(shopOrderList);
    }

    /**
     * 处理来自商品的订单确认
     */
    private void handleConfirmFromProd(OrderConfirmDTO orderConfirmDTO, OrderConfirmVO orderConfirmVO, OrderAmountContext orderAmountContext) {
        //OrderConfirmVO:{收货地址（已处理）,ShopOrder:{shopId,shopName,List<OrderItem>:[{}]},totalCount,totalMoney,actualTotal,transfee,shopReduce}
        ProdConfirmModel orderItem = orderConfirmDTO.getOrderItem();
        List<ShopOrder> shopOrderList = new ArrayList<>(1);
        ShopOrder shopOrder = new ShopOrder();
        shopOrder.setShopId(orderItem.getShopId());
        List<ShopInfoDTO> shopInfoDTOList = shopFeignClient.getShopInfoDTOList(Set.of(orderItem.getShopId()));
        if (CollectionUtils.isEmpty(shopInfoDTOList)) {
            shopOrder.setShopName("该店铺信息是在店铺信息获取失败时所返回的数据");
            log.error("handleConfirmFromProd 获取店铺信息失败");
        } else {
            shopOrder.setShopName(shopInfoDTOList.get(0).getShopName());
        }
        List<OrderItem> orderItemList = new ArrayList<>(1);
        OrderItem item = new OrderItem();
        List<SkuDTO> skuDTOList = prodFeignClient.getSkuDTOListBySkuIds(Set.of(orderItem.getSkuId()));
        if (CollectionUtils.isEmpty(skuDTOList)) {
            throw new BusinessException("商品信息获取失败");
        }
        BeanUtil.copyProperties(skuDTOList.get(0), item);
        item.setShopId(orderItem.getShopId());
        item.setProdCount(orderItem.getProdCount());
        item.setProductTotalAmount(item.getPrice().multiply(BigDecimal.valueOf(orderItem.getProdCount())));
        orderItemList.add(item);
        orderAmountContext.setCommodities(orderItemList.stream().map(mapItem -> {
            Commodity commodity = new Commodity();
            commodity.setSkuId(mapItem.getSkuId());
            commodity.setPrice(mapItem.getPrice());
            commodity.setCount(mapItem.getProdCount());
            return commodity;
        }).toList());
        shopOrder.setShopOrderItems(orderItemList);
        shopOrderList.add(shopOrder);
        orderConfirmVO.setShopOrders(shopOrderList);
    }
}
